//go:build js && wasm

// bolt implements the webassembly facing functions required for
// tvixbolt.
package main

import (
	"fmt"
	"syscall/js"

	"tvl.fyi/tvix/eval"
)

func evalNix(this js.Value, input []js.Value) any {
	if len(input) != 1 {
		return "error: evalNix() expects a single string argument"
	}

	if input[0].Type() != js.TypeString {
		return fmt.Sprintf("error: evalNix() expects a string, but got a %s", input[0].Type())
	}

	result, err := eval.EvalNix(input[0].String(), false)
	if err != nil {
		return fmt.Sprint("error: evaluation failed!", err)
	}

	return result.String()
}

func getElementById(id string) js.Value {
	return js.Global().Get("document").Call("getElementById", id)
}

func processInput(this js.Value, _ []js.Value) any {
	code := getElementById("nix-code").Get("value").String()

	if len(code) == 0 {
		getElementById("output-value").Set("textContent", "Enter some Nix code to get started!")
		return nil
	}

	var output string
	result, err := eval.EvalNix(code, false)
	if err != nil {
		output = fmt.Sprintf("evaluation error: %s", err)
	} else {
		output = result.String()
	}

	getElementById("output-value").Set("textContent", output)
	return nil
}

func resetCode(js.Value, []js.Value) any {
	getElementById("nix-code").Set("value", "")
	processInput(js.Null(), nil)
	return nil
}

func main() {
	c := make(chan struct{}, 0)
	js.Global().Set("evalNix", js.ValueOf(js.FuncOf(evalNix)))
	js.Global().Set("processNixInput", js.ValueOf(js.FuncOf(processInput)))
	js.Global().Set("resetCode", js.ValueOf(js.FuncOf(resetCode)))
	<-c
}
